﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using KEW.InterFace;

namespace AutoGam
{
    public class ComCardDevice : ICard
    {
        #region （串口刷卡器）
        [DllImport("mwrf32.dll", EntryPoint = "hex_a", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 hex_a([MarshalAs(UnmanagedType.LPArray)]byte[] hex, [MarshalAs(UnmanagedType.LPArray)]byte[] asc, int len);
        [DllImport("mwrf32.dll", EntryPoint = "a_hex", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 a_hex([MarshalAs(UnmanagedType.LPArray)]byte[] asc, [MarshalAs(UnmanagedType.LPArray)]byte[] hex, int len);
        [DllImport("mwrf32.dll", EntryPoint = "rf_init", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern int rf_init(Int16 port, Int32 baud);
        [DllImport("mwrf32.dll", EntryPoint = "rf_load_key", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_load_key(int dev, byte model, int snr, byte[] key);
        [DllImport("mwrf32.dll", EntryPoint = "rf_reset", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_reset(int dev, int model);
        [DllImport("mwrf32.dll", EntryPoint = "rf_exit", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_exit(int dev);
        [DllImport("mwrf32.dll", EntryPoint = "rf_beep", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_beep(int dev, int m);
        [DllImport("mwrf32.dll", EntryPoint = "rf_request", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_request(int icdev, int mode, out UInt16 tagtype);
        [DllImport("mwrf32.dll", EntryPoint = "rf_anticoll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_anticoll(int icdev, int bcnt, out uint snr);

        [DllImport("mwrf32.dll", EntryPoint = "rf_read", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_read(int icdev, int block, [MarshalAs(UnmanagedType.LPArray)]byte[] data);
        [DllImport("mwrf32.dll", EntryPoint = "rf_HL_read", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_HL_read(int dev, int model, int block, uint snr, byte[] data, ref uint Rsnr);
        [DllImport("mwrf32.dll", EntryPoint = "rf_HL_readhex", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_HL_readhex(int dev, int model, int block, uint snr, byte[] data, ref uint Rsnr);
        [DllImport("mwrf32.dll", EntryPoint = "rf_HL_write", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_HL_write(int dev, int model, int block, ref uint snr, byte[] data);
        [DllImport("mwrf32.dll", EntryPoint = "rf_HL_writehex", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_HL_writehex(Int16 dev, int model, int block, ref uint snr, byte[] data);
        [DllImport("mwrf32.dll", EntryPoint = "rf_write", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_write(int icdev, int block, byte[] data);
        [DllImport("mwrf32.dll", EntryPoint = "rf_check_write", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_check_write(int icdev, uint snr, int mode, int block, byte[] data);

        [DllImport("mwrf32.dll", EntryPoint = "rf_card", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_card(int icdev, int mode, [MarshalAs(UnmanagedType.LPArray)]byte[] snr);
        [DllImport("mwrf32.dll", EntryPoint = "rf_select", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_select(int icdev, uint snr, out byte size);
        [DllImport("mwrf32.dll", EntryPoint = "rf_authentication", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        private static extern Int16 rf_authentication(int icdev, int mode, int secnr);
        #endregion

        private static int _device;
        private static short _result = 0;
        private static uint _serial;
        private static byte[] _key = new byte[7];

        private Boolean _enable;
        private String _flag;

        public Boolean Enable { get { return _enable; } }
        public String Flag { get { return _flag; } }

        public ComCardDevice()
        {
            try
            {
                a_hex(Encoding.ASCII.GetBytes("ffffffffffff"), _key, 12);
                _device = rf_init((short)3, 115200);
                int st = 0;
                if (_device > 0)
                {
                    for (int i = 0; i <= 15; i++)
                    {
                        st += rf_load_key(_device, 0, i, _key);
                    }
                    if (st == 0)
                    {
                        _enable = true;
                        Beep();
                    }
                    else
                    {
                        _enable = false;
                    }
                }
                else
                {
                    _enable = false;
                }
            }
            catch (Exception) { _enable = false; }
        }

        public String GetSerial()
        {
            byte[] snr = new byte[5];
            _result = rf_card(_device, 1, snr);
            if (_result == 0)
            {
                byte[] snr1 = new byte[8];
                hex_a(snr, snr1, 4);
                return System.Text.Encoding.Default.GetString(snr1);
            }
            else
            {
                return String.Empty;
            }
        }

        /// <summary>
        /// 读块区
        /// </summary>
        /// <param name="block">块区号</param>
        /// <returns>返回值</returns>
        public String ReadBlock(Block block)
        {
            if (!Enable) return "";
            byte[] output = new byte[16];
            _result = 0;// com_authentication(_deviceCom, 0, (int)((int)block) / 4);
            if (_result == 0)
            {
                _result = rf_HL_read(_device, 1, (int)block, _serial, output, ref _serial);
                if (_result == 0)
                {
                    return Encoding.GetEncoding("GBK").GetString(output).Split('\0')[0];
                }
                else
                {
                    return String.Empty;
                }
            }
            else
            {
                return String.Empty;
            }
        }

        /// <summary>
        /// 向某一块区中写数据 可写入8个长度的字符
        /// </summary>
        /// <param name="value">信息</param>
        /// <param name="block">块区</param>
        /// <returns>执行结果返回值</returns>
        public Boolean WriteBlock(String value, Block block)
        {
            if (!Enable) return false;
            _result = 0;//com_authentication(_deviceCom, 0, (int)((int)block) / 4);
            if (_result == 0)
            {
                String cut = Left(value, 16);
                byte[] input = Encoding.GetEncoding("GBK").GetBytes(cut);
                _result = rf_HL_write(_device, 1, (int)block, ref _serial, input);
                if (_result == 0)
                {
                    if (ReadBlock(block) == cut)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        public void Beep()
        {
            if (!Enable) return;
            rf_beep(_device, 10);
        }

        /// <summary>
        /// 退出
        /// </summary>
        public void Exit()
        {
            if (_device > 0)
            {
                //_result = rf_reset(_device, 10);
                _result = rf_exit(_device);
                _device = -1;
            }
        }

        private String Left(String data, int len)
        {
            int curLen = 0;
            int curIdx = 0;
            String retStr = "";
            while (curIdx <= data.Length - 1)
            {
                Byte[] curCharBytes = Encoding.GetEncoding("GBK").GetBytes(data[curIdx].ToString());
                if (curLen + curCharBytes.Length <= len)
                {
                    curLen += curCharBytes.Length;
                    retStr += data[curIdx].ToString();
                    curIdx++;
                }
                else
                {
                    break;
                }
                
            }

            return retStr;
        }
    }
}
